//
//  BluetoothManagerTool.swift
//  DKE-Album
//
//  Created by dagny on 2025/9/24.
//  Copyright © 2025 杨东宝. All rights reserved.
//

import Foundation
import CoreBluetooth

// MARK: - 状态枚举
enum ConectState {
    case unknown
    case resetting
    case unsupported
    case unauthorized
    case poweredOff //蓝牙关闭
    case poweredOn //蓝牙开启
    case scanning //扫描中
    case stopScan  //停止扫描
    case noFountDevice //未发现设备
    case noConnectDevice //无法连接设备
    case connecting //正在连接
    case connected  //已连接
    case disconnecting //正在断开连接
    case disconnected //连接已断开
    case serviceDiscovering //正在发现服务
    case characteristicDiscovering //正在发现特征
    case ready //蓝牙已就绪，可通信
    case communication//正在通信
    case CMDDidSend//指令已发送
    case complate//通信完成
    case error(String)
}
// MARK: - 数据接收协议
protocol BluetoothDataReceiver: AnyObject {
    func didReceiveData(_ data: Data, from peripheral: CBPeripheral)
    func didSendData(_ data: Data, to peripheral: CBPeripheral, error: Error?)
}
// MARK: - 蓝牙管理器主类
class BluetoothManagerTool: NSObject {
    
    var overTime:Bool = true
    
    // MARK: - 单例模式
    static let shared = BluetoothManagerTool()
    // MARK: - 属性声明
    private var centralManager: CBCentralManager!
    public var discoveredDevices: [String: DeviceModel] = [:]
    private var connectedPeripheral: CBPeripheral?
    //过滤条件
    public var nameFilter: String?
    // 特征缓存
    private var writeCharacteristic: CBCharacteristic?
    private var readCharacteristic: CBCharacteristic?
    private var notifyCharacteristic: CBCharacteristic?

    // 回调
    var onStateUpdate: ((ConectState) -> Void)?
    var onDeviceDiscovered: (([DeviceModel]) -> Void)?
    weak var dataReceiver: BluetoothDataReceiver?
    // 状态管理
    private(set) var currentState: ConectState = .unknown {
        didSet {
            DispatchQueue.main.async {
                self.onStateUpdate?(self.currentState)
            }
        }
    }
    // 数据发送队列
    private let dataQueue = DispatchQueue(label: "com.bluetooth.dataqueue")
    private var sendDataQueue: [Data] = []
    private var isSending = false

    // MARK: - 初始化
    private override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.global(qos: .background))
    }
    
    // MARK: - 公共方法
    /// 开始扫描设备
    func startScanning() {
        guard centralManager.state == .poweredOn else {
            currentState = .poweredOff
            return
        }
        discoveredDevices.removeAll()
        currentState = .scanning
        //扫描所有设备
        centralManager.scanForPeripherals(withServices: nil, options: [
                CBCentralManagerScanOptionAllowDuplicatesKey: false])
        // 设置扫描超时
        DispatchQueue.main.asyncAfter(deadline: .now() + 20) { [weak self] in
            self?.stopScanning()
        }
    }
    /// 停止扫描
    func stopScanning() {
        centralManager.stopScan()
        if case .scanning = currentState {
            currentState = .stopScan
        }
    }
    // 获取已发现的设备列表
      func getDiscoveredDevices() -> [DeviceModel] {
          return Array(discoveredDevices.values).sorted { $0.rssi > $1.rssi }
      }
    //根据UUIDstring获取设备信息
    func getPeripheralWithUUid(uuid:String) -> CBPeripheral?{
        let uuid =  UUID(uuidString: uuid)
        if uuid != nil {
        let IDS:[UUID] = [uuid!]
            let per =  centralManager.retrievePeripherals(withIdentifiers:IDS)[0]
            return per
        }
        return nil
    }

    // 连接指定设备
    func connect(to device: DeviceModel, timeout: TimeInterval = 5.0) {
        guard centralManager.state == .poweredOn else {
            currentState = .poweredOff //蓝牙关闭
            return
        }
        
        connectedPeripheral = device.per
        currentState = .connecting
        centralManager.connect(device.per!, options: [
            CBConnectPeripheralOptionNotifyOnConnectionKey: true,
            CBConnectPeripheralOptionNotifyOnDisconnectionKey: true,
            CBConnectPeripheralOptionNotifyOnNotificationKey: true
        ])
        // 设置连接超时
        DispatchQueue.main.asyncAfter(deadline: .now() + 20) { [weak self] in
            if self?.overTime  == true{
                self?.currentState = .noConnectDevice
                self?.overTime = true
            }
        }
    }
    /// 断开当前连接
    func disconnect() {
        if let peripheral = connectedPeripheral {
            centralManager.cancelPeripheralConnection(peripheral)
        }
        cleanupConnection()
    }
      /// 获取连接状态
    func isConnected() -> Bool {
          if case .connected = currentState { return true }
          if case .ready = currentState { return true }
          return false
    }
    /// 发送数据到已连接设备
    func sendData(_ data: Data, type: CBCharacteristicWriteType = .withoutResponse,isGetPhotos:Bool) -> Bool {
        guard let peripheral = connectedPeripheral,
              let characteristic = writeCharacteristic else {
            return false
        }
        guard case .ready = currentState else{
            return false
        }
        currentState = .communication
        // 检查数据长度限制
        if data.count > 256 {
            // 大数据分片发送
            sendDataInChunks(data, type: type)
            return true
        } else {
            peripheral.writeValue(data, for: characteristic, type: type)
            if !isGetPhotos {
                DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
                    self?.currentState = .complate
                }
            }
            return true
        }
    }
    private func sendDataInChunks(_ data: Data, type: CBCharacteristicWriteType) {
        let chunkSize = 256
        var offset = 0
        func sendNextChunk() {
            guard offset < data.count else { return }
            DebugLog("正在上传第    \(offset)   字节，总共 \(data.count)")
            let chunkLength = min(chunkSize, data.count - offset)
            let chunk = data.subdata(in: offset..<offset + chunkLength)
            offset += chunkLength
            
            if let peripheral = connectedPeripheral, let characteristic = writeCharacteristic {
                peripheral.writeValue(chunk, for: characteristic, type: type)
                // 添加小延迟避免发送过快
                DispatchQueue.global().asyncAfter(deadline: .now() + 0.01) {
                    sendNextChunk()
                }
            }
        }
        sendNextChunk()
    }
}

// MARK: - CBCentralManagerDelegate
extension BluetoothManagerTool: CBCentralManagerDelegate {
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
            currentState = .poweredOn
            print("蓝牙已开启")
            
        case .poweredOff:
            currentState = .poweredOff
            print("蓝牙已关闭")
            
        case .resetting:
            currentState = .resetting
            print("蓝牙重置中")
            
        case .unauthorized:
            currentState = .unauthorized
            print("蓝牙权限被拒绝")
            
        case .unsupported:
            currentState = .unsupported
            print("设备不支持蓝牙")
            
        case .unknown:
            currentState = .unknown
            print("蓝牙状态未知")
            
        @unknown default:
            currentState = .unknown
            print("未知蓝牙状态")
        }
    }
    
    //扫描设备结果回调
    func centralManager(_ central: CBCentralManager,
                       didDiscover peripheral: CBPeripheral,
                       advertisementData: [String: Any],
                        rssi RSSI: NSNumber) {
        
        let deviceName = peripheral.name ?? advertisementData[CBAdvertisementDataLocalNameKey] as? String ?? ""
        let rssiValue = RSSI.intValue

        if deviceName == "" {
            return
        }

        // 1. 从广播数据中获取制造商数据
         if let manufacturerData = advertisementData[CBAdvertisementDataManufacturerDataKey] as? Data {
             // manufacturerData 的格式需要你与硬件工程师约定
             // 例如，假设MAC地址在特定的字节位置
             let macAddressData = manufacturerData.subdata(in: 2..<8) // 举例，从第2字节开始取6字节
             let macAddressString = macAddressData.map { String(format: "%02X", $0) }.joined(separator: ":")
             print("从广播中获取的MAC地址: \(macAddressString)")
         }
    
        if nameFilter == "" || nameFilter == nil || deviceName.contains(nameFilter!) {
            let device = DeviceModel(name: deviceName, ID: peripheral.identifier.uuidString, rssi: rssiValue, peripheral: peripheral)
            // 更新设备列表
            discoveredDevices[peripheral.identifier.uuidString] = device
            // 通知外部设备列表更新
            DispatchQueue.main.async {
                self.onDeviceDiscovered?(self.getDiscoveredDevices())
            }
        }
        print("发现设备: \(deviceName), RSSI: \(rssiValue), UUID: \(peripheral.identifier)")
    }
    func centralManager(_ central: CBCentralManager,
                       didConnect peripheral: CBPeripheral) {
        print("设备连接成功: \(peripheral.name ?? "未知设备")")
        self.overTime = false
        currentState = .connected
        discoverServices(for: peripheral)
    }
    
    func centralManager(_ central: CBCentralManager,
                       didFailToConnect peripheral: CBPeripheral,
                       error: Error?) {
        let errorMessage = error?.localizedDescription ?? "未知错误"
        print("连接失败: \(errorMessage)")
        currentState = .error("连接失败: \(errorMessage)")
        cleanupConnection()
    }
    func centralManager(_ central: CBCentralManager,
                       didDisconnectPeripheral peripheral: CBPeripheral,
                       error: Error?) {
        if let error = error {
            print("设备断开连接: \(error.localizedDescription)")
        } else {
            print("设备正常断开")
        }
        currentState = .error("设备已断开")
        cleanupConnection()
    }
}
extension BluetoothManagerTool{
  
    //开始发现服务
    private func discoverServices(for peripheral: CBPeripheral) {
        currentState = .serviceDiscovering
        peripheral.delegate = self
        //发现服务
        peripheral.discoverServices(nil)
    }
    // MARK: - 私有方法
    private func cleanupConnection() {
        writeCharacteristic = nil
        readCharacteristic = nil
        notifyCharacteristic = nil
        connectedPeripheral = nil
        currentState = .disconnected
    }
    //发现特征处理
    private func setupCharacteristics(for service: CBService) {
        guard let characteristics = service.characteristics else { return }
        
        for characteristic in characteristics {
            // 检查特征属性
            if characteristic.properties.contains(.write) || characteristic.properties.contains(.writeWithoutResponse) {
                writeCharacteristic = characteristic
                print("找到写入特征: \(characteristic.uuid)")
            }
            
            if characteristic.properties.contains(.read) {
                readCharacteristic = characteristic
                print("找到读取特征: \(characteristic.uuid)")
            }
            
            if characteristic.properties.contains(.notify) {
                notifyCharacteristic = characteristic
                connectedPeripheral?.setNotifyValue(true, for: characteristic)
                print("找到通知特征: \(characteristic.uuid) - 已启用通知")
            }
        }
        
        // 如果找到了必要的特征，更新状态为准备就绪
        if writeCharacteristic != nil {
            currentState = .ready
            print("蓝牙准备就绪，可以发送数据")
        } else {
            currentState = .error("未找到可写入的特征")
        }
    }
    
}
// MARK: - CBPeripheralDelegate
extension BluetoothManagerTool: CBPeripheralDelegate {
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        if let error = error {
            currentState = .error("发现服务失败: \(error.localizedDescription)")
            return
        }
        guard let services = peripheral.services, !services.isEmpty else {
            currentState = .error("未找到任何服务")
            return
        }
        print("发现 \(services.count) 个服务")
        currentState = .characteristicDiscovering
        // 发现每个服务的特征
        for service in services {
            print("服务 UUID: \(service.uuid.uuidString)")
            //发现特征
            peripheral.discoverCharacteristics(nil, for: service)
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral,
                   didDiscoverCharacteristicsFor service: CBService,
                   error: Error?) {
        if let error = error {
            currentState = .error("发现特征失败: \(error.localizedDescription)")
            return
        }
        setupCharacteristics(for: service)
    }
    
    func peripheral(_ peripheral: CBPeripheral,
                   didWriteValueFor characteristic: CBCharacteristic,
                   error: Error?) {
        let data = characteristic.value ?? Data()
        
        DispatchQueue.main.async {
            self.dataReceiver?.didSendData(data, to: peripheral, error: error)
        }
        if let error = error {
            print("数据发送失败: \(error.localizedDescription)")
        } else {
            print("数据发送成功")
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral,
                   didUpdateValueFor characteristic: CBCharacteristic,
                   error: Error?) {
        if let error = error {
            print("接收数据错误: \(error.localizedDescription)")
            return
        }
        
        guard let data = characteristic.value else { return }
        
//        print("接收到数据: \(data.count) 字节")
        
        DispatchQueue.main.async {
            self.dataReceiver?.didReceiveData(data, from: peripheral)
        }
    }
    func peripheral(_ peripheral: CBPeripheral,
                   didUpdateNotificationStateFor characteristic: CBCharacteristic,
                   error: Error?) {
        if let error = error {
            print("通知设置失败: \(error.localizedDescription)")
        } else {
            print("通知设置: \(characteristic.isNotifying ? "开启" : "关闭")")
        }
    }
}
